/**
 * RecvInformation.java
 * 版权所有(C) 2013
 * 创建者:cuiran 2013-11-27 下午12:01:53
 */
package com.ghyf.mplay.net.common;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.content.Intent;

import com.ghyf.mplay.net.data.ModuleTextBase;
import com.ghyf.mplay.net.data.ModuleTextData;
import com.ghyf.mplay.net.data.PriorityTextData;
import com.ghyf.mplay.util.LogUtil;
import com.ghyf.mplay.value.ConstantValue;



/**
 * 监听文字消息 
 * @author cuiran
 * @version 1.0.0
 */
public class RecvInformation extends RecvBase implements Runnable {


	public RecvInformation(int listenPort, int serverPort,Context context){
		port_listen = listenPort;
		port_server = serverPort;
		mContext=context;
	}

	public void run() {
		LogUtil.i(TAG, "RecvInformation.run() -- start!");
		try
		{
			LogUtil.i(TAG, "RecvInformation.run() -- try....");
			
			DatagramSocket so_out = new DatagramSocket();
			DatagramSocket so_in = new DatagramSocket(port_listen);

			LogUtil.i(TAG, "RecvInformation.run() -- Recv Socket Created!");
			so_in.setSoTimeout(100);
			byte[] buf_in1 = new byte[GData.maxPacketLength];
			byte[] buf_in = new byte[GData.maxPacketLength];
			DatagramPacket pkt_in = new DatagramPacket(buf_in, buf_in.length);
			LogUtil.i(TAG, "RecvInformation.run() -- Recv Pakcet Created!");
			
		//	LogUtil.i(TAG, "RecvInformation.run() -- Begin Receiving...");
			while(!isStop)
			{
				try
				{
					so_in.receive(pkt_in);
			//		LogUtil.i(TAG, "RecvInformation.run() -- receiv() returned!");
					LogUtil.i(TAG, "RecvInformation.run() -- Recv PacketLength(" + pkt_in.getLength() + ")");
				
					// Check Packet Length
					int recvLength = pkt_in.getLength();
					if(recvLength < packetHeaderLength)
					{
						LogUtil.i(TAG, "RecvInformation.run() -- Received bad Packet, Length=" + recvLength);
						continue;
					}
					
					// Analyse the Packet Header
					byte[] buf_recv = pkt_in.getData();
					assert(buf_recv.length == recvLength);
					ByteArrayInputStream baInPacketHeader = new ByteArrayInputStream(buf_recv, 0, packetHeaderLength);
					DataInputStream dInHeader = new DataInputStream(baInPacketHeader);
					byte stx = dInHeader.readByte();
					short cmdID = dInHeader.readShort();
					int timestamp = dInHeader.readInt();
					int tickCount = dInHeader.readInt();
					byte[] buf_temp = new byte[recvLength];
					dInHeader.read(buf_temp, 0, deviceIDLength);
					String deviceID = new String(buf_temp, 0, deviceIDLength,RecvBase.charset).trim();
					dInHeader.skipBytes(packetHeaderReservedLength);
					short dataLength = dInHeader.readShort();
					
					// Check & LogUtil
					if(stx != STX_SERVER2CLIENT || dataLength + packetHeaderLength != recvLength)
					{
						LogUtil.i(TAG, "RecvInformation.run() -- Received BAD Packet, stx=" + stx + " cmdID=" + cmdID + 
								" timestamp=" + timestamp + "tickCount=" + tickCount + " deviceID=" + deviceID + " recvLength=" + recvLength);
						continue;
					}
					LogUtil.i(TAG, "RecvInformation.run() -- Received Information Packet, stx=" + stx + " cmdID=" + cmdID + 
							" timestamp=" + timestamp + "tickCount=" + tickCount + " deviceID=" + deviceID + " recvLength=" + recvLength);

					// Get server address
					InetAddress inetAddr_in = pkt_in.getAddress();
					String ip_in = inetAddr_in.getHostAddress();
					int port_in = pkt_in.getPort();
					LogUtil.i(TAG, "RecvInformation.run() -- Recv Packet from: IP(" + ip_in + ":" + port_in + ") Length(" + pkt_in.getLength() + ")");
					
					// Analyse Cmd Data
					switch(cmdID)
					{
					case CMD_TEXT_SETPROIRITY:
					{
						// Get TextData Value 
						if(dataLength != setPriorityTextLength || recvLength != packetHeaderLength + setPriorityTextLength)
						{
							// send nack
							String strExecDes = new String("已收到紧急消息, 但是数据长度(" + dataLength + ") 接收长度(" + recvLength + " 错误!");
							sendAck(cmdID, timestamp, tickCount, (short)ERR_PH_DATALENGTH, (byte)0, strExecDes, so_out, inetAddr_in);      
							break;
						}
						
						PriorityTextData textData = new PriorityTextData();
						textData.GetTextData(buf_recv, packetHeaderLength, setPriorityTextLength);
						if(textData.IsInitialed())
						{
							LogUtil.i(TAG, "RecvInformation.run() -- Received CMD_TEXT_SETPROIRITY CMD, "  + textData.toString());
							
							// Do Actions here!!
					        // short ret = HandleTextSetProirity(textData);
							Intent myIntent = new Intent(RecvBase.ACTION_CMD_CONTROL);  
							myIntent.putExtra("cmd", (short)cmdID);
				            myIntent.putExtra(ConstantValue.EXTRA_OBJ, textData);
				            myIntent.setAction(RecvBase.ACTION_CMD_CONTROL);  
				            mContext.sendBroadcast(myIntent);  
							// SendAck
							String strExecDes = new String("已收到紧急消息指令!" + textData.toString());
							sendAck(cmdID, timestamp, tickCount, (short)NET_ACK /*ret*/, (byte)0, strExecDes, so_out, inetAddr_in);      	
						}
						else
						{
							LogUtil.i(TAG, "RecvInformation.run() -- Received CMD_TEXT_SETPROIRITY CMD, but canot analyse data!");
							
							// sendAck
							String strExecDes = new String("已收到紧急消息指令,但是不能分析数据!");
							sendAck(cmdID, timestamp, tickCount, (short)ERR_PH_DATAERROR, (byte)0, strExecDes, so_out, inetAddr_in);      	
						}
						
						pkt_in.setData(buf_in1);
						break;
					}
					case CMD_TEXT_SETNORMAL:
					{
						if(dataLength < 0 || dataLength > maxSetNormalTextLength || recvLength != packetHeaderLength + dataLength)
						{
							// send nack
							String strExecDes = new String("I have Received CMD_TEXT_SETNORMAL CMD, but dataLength(" + dataLength + ") RecvLength(" + recvLength + " Error!");
							sendAck(cmdID, timestamp, tickCount, (short)ERR_PH_DATALENGTH, (byte)0, strExecDes, so_out, inetAddr_in);      
							break;
						}
						LogUtil.i(TAG, "RecvInformation.run() -- Received CMD_TEXT_SETNORMAL CMD, dataLength(" + dataLength + ") RecvLength(" + recvLength + " !");
			//			PriorityTextData textData = new PriorityTextData();
			//			textData.GetTextData(buf_recv, packetHeaderLength, dataLength);
						ByteArrayInputStream baInPacketData = new ByteArrayInputStream(buf_recv, packetHeaderLength, dataLength);
						DataInputStream dInData = new DataInputStream(baInPacketData);
						
						String strMsg = new String("");
						int nReadLength = 0;
						int nTextCount = 0;
						ModuleTextBase textBase=new ModuleTextBase();
						List<ModuleTextData> textDatas=new ArrayList<ModuleTextData>();
						while(nReadLength < dataLength)
						{
							short uid = dInData.readShort();
							nReadLength += 2;
							short textLen = dInData.readShort();
							nReadLength += 2;
							if(textLen>1314){
								String strExecDes = new String("I have Received CMD_TEXT_SETNORMAL CMD, but textLen(" + textLen + ") is greater than 1314 Error!");
								sendAck(cmdID, timestamp, tickCount, (short)ERR_PH_DATALENGTH, (byte)0, strExecDes, so_out, inetAddr_in);    
								break;
								
							}
							int nRead = dInData.read(buf_temp, 0, textLen);
							if(nRead == -1)	{
								break;		// the end of the stream has been reached.
							}
							String textContent = new String(buf_temp, 0, textLen,"gb2312");
							nReadLength += textLen;
							
							// gData.AddNormalText(uid, textContent);
							nTextCount ++;
							ModuleTextData textData=new ModuleTextData(uid,textContent);
							textDatas.add(textData);
							strMsg += new String(" Text" + nTextCount + " uid=" + uid + " content=" + textContent + "  ");
						}
						textBase.setModulelist(textDatas);
						
						LogUtil.i(TAG, "RecvInformation.run() -- Received CMD_TEXT_SETNORMAL CMD, "  + strMsg);
						
						// Do Actions here!!
						Intent myIntent = new Intent(ConstantValue.CMD_RECEIVER);  
			            myIntent.putExtra(ConstantValue.EXTRA_TYPE, cmdID);
			            myIntent.putExtra(ConstantValue.EXTRA_OBJ, textBase);
			            myIntent.setAction(ConstantValue.CMD_RECEIVER);  
			            mContext.sendBroadcast(myIntent);  
						
				        // short ret = HandleTextSetNormal();
						
						// sendAck
						String strExecDes = new String("已收到普通文本指令! " + strMsg);
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK /*ret*/, (byte)0, strExecDes, so_out, inetAddr_in);      
						pkt_in.setData(buf_in1);
						break;
					}
					case CMD_TEXT_STOP:
					{
						// Get TextData Value 
						if(dataLength != stopTextLength || recvLength != packetHeaderLength + stopTextLength)
						{
							// send nack
							String strExecDes = new String("I have Received CMD_TEXT_STOP CMD, but dataLength(" + dataLength + ") RecvLength(" + recvLength + " Error!");
							sendAck(cmdID, timestamp, tickCount, (short)ERR_PH_DATALENGTH, (byte)0, strExecDes, so_out, inetAddr_in);      
							break;
						}
						ByteArrayInputStream baInPacketData = new ByteArrayInputStream(buf_recv, packetHeaderLength, dataLength);
						DataInputStream dInData = new DataInputStream(baInPacketData);
						String strMsg = new String("");
						short uid=dInData.readShort();
						strMsg+=uid;
						dInData.read(buf_temp, 0, 16);
						String textId = new String(buf_temp, 0, 16).trim();
						strMsg+=textId;
						dInData.read(buf_temp, 0, 14);
						String Reseved = new String(buf_temp, 0, 14).trim();
						strMsg+=Reseved;
						ModuleTextData textData=new ModuleTextData(uid,textId);
						// sendAck
						String strExecDes = new String("已收到停止紧急消息指令! "+strMsg);
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK /*ret*/, (byte)0, strExecDes, so_out, inetAddr_in);      
						
						LogUtil.i(TAG, "RecvInformation.run() -- Received CMD_TEXT_STOP CMD!");
						
						// Do Actions here!!
						Intent myIntent = new Intent(RecvBase.ACTION_CMD_CONTROL);  
						myIntent.putExtra("cmd", cmdID);
						myIntent.putExtra(ConstantValue.EXTRA_TYPE, cmdID);
			            myIntent.putExtra(ConstantValue.EXTRA_OBJ, textData);
			            myIntent.setAction(RecvBase.ACTION_CMD_CONTROL);  
			            mContext.sendBroadcast(myIntent);  
						
						pkt_in.setData(buf_in1);
						break;
					}
					default:
					{
						sendAck(cmdID, timestamp, tickCount, (short)ERR_PH_CMDID, (byte)0, new String("Unknown Cmd_ID"), so_out, inetAddr_in);
					}}
				}
				catch(IOException e)
				{
//					LogUtil.e(TAG, "RecvInformation.run() --  catch IOException: receive() " ,e);
				}
				finally
				{
//					LogUtil.i(TAG, "RecvInformation.run() -- finally !!");
				}
			}
			so_in.close();
	        so_out.close();
		}
		catch (SocketException e)
		{ 
			LogUtil.e(TAG, "RecvInformation.run() -- catch SocketException: " ,e);
        }
		catch(Exception e)
		{
			LogUtil.e(TAG, "RecvInformation.run() -- catch Exception: " ,e);
		}
		finally
		{
		}	
		LogUtil.i(TAG, "RecvInformation.run() -- exit!");	
	}
}
